"use strict"

var loadImage = require("./imageLoader")
var timeline = require("./timeline")
//初始化
var STATUS_INITIAL = 0
//开始
var STATUS_START = 1  
//结束
var STATUS_STOP = 2

//定义一个同步任务
var TASK_SYNC = 0
//定义一个异步任务
var TASK_ASYNC = 1

/**
 * 简单的函数封装，执行callback
 * @param {fn} callback 执行函数
 */
function next(callback){
  callback && callback()
}

function Animation(){
  this.taskQueue = []
  this.index = 0
  this.timeline = new timeline()
  this.state = STATUS_INITIAL
}

/**
 * 添加一个同步任务，预加载图片
 * @param {*} imgList 图片列表
 */
Animation.prototype.loadImage = function(imgList){
  var taskFn = function(next){
    // imgList.slice() 进行数组深拷贝
    loadImage(imgList.slice(),next)
  }
  var type = TASK_SYNC
  
  return this._add(taskFn,type)
}

/**
 * 添加一个异步定时任务，通过定时改变图片背景位置，实现帧动画
 * @param {*} ele dom对象
 * @param {*} positions 背景位置数组
 * @param {*} imgUrl 图片地址
 */
Animation.prototype.changePosition = function(ele,positions,imgUrl){
  var len = positions.length
  var taskFn
  var type

  if(len){
    var me = this
    taskFn = function(){
      if (imgUrl) {
        ele.style.backgroundImage = `url(${imgUrl})`
      }
      // |0   向下取整 相当于math.floor,速度更快
      //获得当前背景图位置
      var index = Math.min(time / me.interval | 0 ,len-1)
      var position = positions[index].splice(" ")
      //改变dom对象的背景图片位置
      ele.style.backgroundPosition = position[0] + "px " + position[1] + "px"
      if (index === len-1){
        next()
      }
    }
    type = TASK_ASYNC
  }else {
    taskFn = next
    type = TASK_SYNC
  }

  return this._add(taskFn,type)
}

/**
 * 添加一个异步定时任务，通过定时改变img标签的src,实现帧动画
 * @param {*} ele img元素
 * @param {*} imgList 图片列表
 */
Animation.prototype.changeSrc = function(ele,imgList){
  var len = imgList.length
  var taskFn
  var type

  if(len){
    var me = this
    taskFn = function(next,time){
      // |0   向下取整 相当于math.floor,速度更快
      //获得当前背景图位置
      var index = Math.min(time / me.interval | 0 ,len-1)
      //改变img的地址
      ele.src = imgList[index]
      if (index === len-1){
        next()
      }
    }
    type = TASK_ASYNC
  }else {
    taskFn = next
    type = TASK_SYNC
  }

  return this._add(taskFn,type)
}

/**
 * 高级用法，添加一个异步定时执行的任务
 * 该任务自定义动画每帧执行的任务函数
 * @param {*} taskFn 自定义每帧执行的任务函数
 */
Animation.prototype.enterFrame = function(taskFn){
  return this._add(taskFn,TASK_ASYNC)
}

/**
 * 添加一个同步任务，可以在上一个任务完成后执行的回调函数
 * @param {*} callback  回调函数
 */
Animation.prototype.then = function(callback){
  var taskFn = function(next){
    callback()
    next()
  }

  var type = TASK_SYNC

  return this._add(taskFn,type)
}

/**
 * 开始执行任务，异步定义任务执行的间隔
 * @param {*} interval 间隔
 */
Animation.prototype.start = function(interval){
  if (this.state=== STATUS_START){
    return this
  }
  //如果任务链中没有任务，则返回
  if (!this.taskQueue.length){
    return this
  }
  this.state = STATUS_START
  this.interval = interval
  this._runTask()
  return this
}

/**
 * 添加一个同步任务，该任务就是回退到上一个任务中
 * 实现重复上一个任务的效果，可以定义重复的次数
 * @param {*} times 重复次数
 */
Animation.prototype.repeat = function(times){
    var me = this
    var taskFn = ()=>{
      if (typeof times === "undefined"){
        //无限退队到上一个任务
        me.index--
        me._runTask()
        return
      }
      if (times){
        times--
        //回退
        me.index--
        me._runTask()
      }else{
        //达到重复次数，跳转下一个任务
        var task = me.taskQueue[me.index]
        me._next(task)
      }
    }
    var type = TASK_SYNC

    return this._add(taskFn,type)
}

/**
 * 添加一个同步任务，相当于repeat()更友好，无限次
 */
Animation.prototype.repeatForever = function(){
  return this.repeat()
}

/**
 * 设置当前任务执行结束后到下一个任务开始前的等待时间
 * @param {*} time 时长
 */
Animation.prototype.wait = function(time){
  if (this.taskQueue && this.taskQueue.length>0){
    this.taskQueue[this.taskQueue.length-1].wait = time
  }

  return this
}

/**
 * 暂停当前异步定时任务
 */
Animation.prototype.pause = function(){
  if (this.state===STATUS_START){
    this.state = STATUS_STOP
    this.timeline.stop()
    return this
  }
  return this
}

/**
 * 重新执行上一次暂停的异步任务
 */
Animation.prototype.restart = function(){
  if (this.state === STATUS_STOP) {
     this.state = STATUS_START
     this.timeline.restart()
     return this
  }
  return this
}

/**
 * 释放资源
 */
Animation.prototype.dispose = function(){
  if (this.state !== STATUS_INITIAL){
    this.state = STATUS_INITIAL
    this.taskQueue = null
    this.timeline.stop()
    this.timeline = null
    return this
  }
  return this
}

/**
 * 添加一个任务到任务队列中
 * @param {object} taskFn 任务方法
 * @param {string} type 任务类型
 * @private
 */
Animation.prototype._add = function(taskFn,type){
  this.taskQueue.push({
    taskFn:taskFn,
    type:type
  })
  return this
}

/**
 * 执行任务
 * @private
 */
Animation.prototype._runTask = function(){
  if (!this.taskQueue || this.state !==STATUS_START){
    return
  }

  //任务执行完毕
  if (this.index === this.taskQueue.length){
    this.dispose()
    return 
  }
  
  //获得任务链上当前任务
  var task = this.taskQueue[this.index]
  if (task.type === TASK_SYNC){
    this._syncTask(task)
  }else{
    this._asyncTask(task)
  }
}

/**
 * 执行同步任务
 * @param {object} task 执行的 任务
 * @private
 */
Animation.prototype._syncTask = function(task){
  var _this = this
  var next = function(){
    //切换下一个任务
    _this._next(task)
  }
  var taskFn = task.taskFn
  taskFn(next)
}

/**
 * 执行异步任务
 * @param {object} task 执行的任务
 * @private
 */
Animation.prototype._asyncTask = function(task){
  var me = this
  //定义每一帧执行的回调函数
  var enterFrame = function(time){
    var taskFn = task.taskFn
    var next = function(){
      //停止当前任务
      me.timeline.stop()
      me._next(task)
    }
    taskFn(next,time)
  }

  this.timeline.onenterframe = enterFrame
  this.timeline.start(this.interval)
}

/**
 * 切换到下一个任务,支持如果当前任务需要等待，则延时
 * @param task 当前任务
 * @private
 */
Animation.prototype._next = function(task){
  this.index++
  var me = this
  task.wait ? setTimeout(() => {
    me._runTask()
  }, task.wait):this._runTask()
  
}

module.exports = function(){
  return new Animation()
}
